#include <iostream>
#include <memory>
#include <list>
#include <vector>
#include <unordered_map>
#include <thread>
#include "mutex_lock.h"

using namespace std;

namespace {

class CB;
class CA {
  public:
    CA() {
      std::cout << "CA()" << std::endl;
    }
    ~CA() {
      std::cout << "~CA()" << std::endl;
    }
    void set_ptr(std::shared_ptr<CB>& ptr) {
      m_ptr_b = ptr;
    }
  private:
    // weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数
    // 既然weak_ptr并不改变其所共享的shared_ptr实例的引用计数，那就可能存在weak_ptr指向的对象被释放掉这种情况。
    // 这时，就不能使用weak_ptr直接访问对象。那么如何判断weak_ptr指向对象是否存在呢？C++中提供了lock函数来实现该功能。
    // 如果对象存在，lock()函数返回一个指向共享对象的shared_ptr(引用计数会增1)，否则返回一个空shared_ptr。
    // weak_ptr还提供了expired()函数来判断所指对象是否已经被销毁。
    std::weak_ptr<CB> m_ptr_b;
};

class CB {
  public:
    CB() {
      std::cout << "CB()" << std::endl;
    }
    ~CB() {
      std::cout << "~CB()" << std::endl;
    }
    void set_ptr(std::shared_ptr<CA>& ptr) {
      m_ptr_a = ptr;
    }
  private:
    std::shared_ptr<CA> m_ptr_a;
};

class Test {
  public:
    Test(int id) : m_id(id) {}
    void showID() {
      std::cout << m_id << std::endl;
    }
  private:
    int m_id;
};

void thread2(std::weak_ptr<Test> t) {
  std::this_thread::sleep_for(std::chrono::seconds(2));
  std::shared_ptr<Test> sp = t.lock();
  if(sp)
    sp->showID();                      // 打印结果：2
}

class Frame {};

void Handle() {
  std::shared_ptr<Frame> f(new Frame());
  std::weak_ptr<Frame> f1(f);                     // shared_ptr直接构造
  std::weak_ptr<Frame> f2 = f;                    // 隐式转换
  std::weak_ptr<Frame> f3(f1);                    // 拷贝构造函数
  std::weak_ptr<Frame> f4 = f1;                   // 拷贝构造函数
  std::weak_ptr<Frame> f5;
  f5 = f;                                         // 拷贝赋值函数
  f5 = f2;                                        // 拷贝赋值函数
  std::cout << f.use_count() << std::endl;        // 1

  std::shared_ptr<CA> ptr_a(new CA());
  std::shared_ptr<CB> ptr_b(new CB());
  ptr_a->set_ptr(ptr_b);
  ptr_b->set_ptr(ptr_a);
  std::cout << "ptr_a: " << ptr_a.use_count() << " ptr_b: " << ptr_b.use_count() << std::endl;

  std::shared_ptr<Test> sp = std::make_shared<Test>(2);
  std::thread t2(thread2, sp);
  // t2.join();
  t2.detach();
}

class Listener {
public:
    void handleMessage(int msgid) {}
};

// 存储监听者注册的感兴趣的事件
unordered_map<int, list<weak_ptr<Listener>>> listenerMap;

// 观察者观察到事件发生，转发到对该事件感兴趣的监听者
void dispatchMessage(int msgid) {
  auto it = listenerMap.find(msgid);
  if (it != listenerMap.end()) {
    for (auto it1 = it->second.begin(); it1 != it->second.end(); ++it1) {
      shared_ptr<Listener> ps = it1->lock();            // 智能指针的提升操作，用来判断监听者对象是否存活
      if (ps != nullptr) {                              // 监听者对象如果存活，才通知处理事件
        ps->handleMessage(msgid);
      } else {
        it1 = it->second.erase(it1);                    // 监听者对象已经析构，从map中删除这样的监听者对象
      }
    }
  }
}

class Observer {
public:
    void update() {}
};

class Observable // not 100% thread safe!
{
public:
  void register_(weak_ptr<Observer> x); // 参数类型可用 const weak_ptr<Observer>&
  // void unregister(weak_ptr<Observer> x); // 不需要它
  void notifyObservers();

private:
  mutable MutexLock mutex_;
  std::vector<weak_ptr<Observer> > observers_;
  typedef std::vector<weak_ptr<Observer> >::iterator Iterator;
};

void Observable::notifyObservers()
{
  MutexLockGuard lock(mutex_);
  Iterator it = observers_.begin(); // Iterator 的定义见第 49 行
  while (it != observers_.end())
  {
    shared_ptr<Observer> obj(it->lock()); // 尝试提升，这一步是线程安全的
    if (obj)
    {
      // 提升成功，现在引用计数值几乎总是大于等于 2。（想想为什么？）
      obj->update(); // 没有竞态条件，因为 obj 在栈上，对象不可能在本作用域内销毁
      ++it;
    }
    else
    {
      // 对象已经销毁，从容器中拿掉 weak_ptr
      it = observers_.erase(it);
    }
  }
}


}

void HandleWeekPtr() {
    Handle();
}
